package com.googlecode.librank;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class GetLibraryNameFromJar {
	static String getPackageNameFromClassName(String className) {

		String splits[] = className.split("/");
		String packageName = "";

		for (int i = 0; i < splits.length; i++) {
			packageName += splits[i];
			if (i != splits.length - 1) {
				packageName += ".";
			}
		}

		return packageName;
	}

	/**
	 * Check which one is subset of which.
	 * 
	 * @param packageName1
	 * @param packageName2
	 * @return null if there is no subset relationship subset package name if
	 *         there is
	 */
	String whichOneIsSubSet(String packageName1, String packageName2) {
		String packageNameSplits1[] = packageName1.split(".");
		String packageNameSplits2[] = packageName2.split(".");

		for (int i = 0; i < Math.min(packageNameSplits1.length,
				packageNameSplits2.length); i++) {
			if (!packageNameSplits1[i].equals(packageNameSplits2[i])) {
				return null;
			}
		}

		// return the shortest one
		return packageName1.length() < packageName2.length() ? packageName1
				: packageName2;
	}

	/**
	 * Get all package name from a given jar file
	 * 
	 * @param jarFileName
	 * @return
	 * @throws IOException
	 */
	static Set<String> getPackageNames(String jarFileName) throws IOException {
		Set<String> packageNames = new HashSet<String>();
		// jar file
		JarFile inJar = new JarFile(jarFileName);

		// get all jar entries
		Enumeration<JarEntry> entries = inJar.entries();

		while (entries.hasMoreElements()) {
			// get a jar entry and input stream
			JarEntry entry = entries.nextElement();
			packageNames.add(getPackageNameFromClassName(entry.getName()));
			// packageNames.add(entry.getName());
		}

		inJar.close();

		return packageNames;
	}

	/**
	 * Get possible library name from package names Assume: a jar file includes
	 * only one or two libraries
	 * 
	 * @param packageNames
	 * @return
	 * @throws IOException
	 */
	Set<String> getLibNames(Set<String> packageNames) throws IOException {
		Set<String> libNames = new HashSet<String>();

		for (String libNameCandidate : packageNames) {
			boolean addNewOne = true;

			for (String libName : libNames) {
				String subSet = whichOneIsSubSet(libName, libNameCandidate);
				if (libNameCandidate.equals(subSet)) {
					libNames.remove(libName);
				} else if (libName.equals(subSet)) {
					addNewOne = false;
					break;
				}
			}

			if (addNewOne) {
				libNames.add(libNameCandidate);
			}
		}

		return libNames;
	}

	public void testGetPackagenames() throws IOException {
		Set<String> packagenames = getPackageNames("/home/hunkim/workspace/objCapture/lib/xstream-1.3.jar");
		List<String> packageList = new ArrayList<String>(packagenames);
		Collections.sort(packageList);
		for (String name : packageList) {
			System.out.println(name);
		}
	}

	public static void main(String args[]) throws IOException {
		if (args.length != 1) {
			System.err.println("Usage: GetLibraryNameFromJar <jar>");
			return;
		}
		Set<String> packagenames = getPackageNames(args[0]);
		List<String> packageList = new ArrayList<String>(packagenames);
		Collections.sort(packageList);
		for (String name : packageList) {
			System.out.println(name);
		}
	}
}
